#include "drv_usb.h"

#define USB_IOEN        0x00000080
#define USB_PHY_V33     0x00000040
#define UDP_PUE_MASK    0x0000000C
#define UDP_PUE_DISABLE 0x00000000
#define UDP_PUE_35UA    0x00000004
#define UDP_PUE_10K     0x00000008
#define UDP_PUE_1K5     0x0000000C

#define UDM_PUE_MASK    0x00000003
#define UDM_PUE_DISABLE 0x00000000
#define UDM_PUE_35UA    0x00000001
#define UDM_PUE_10K     0x00000002
#define UDM_PUE_1K5     0x00000003

void usb_dc_low_level_init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBFS, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure = { 0 };

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_16;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_17;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    PWR_VDD VDD_Voltage = PWR_VDD_SupplyVoltage();
    if( VDD_Voltage ==  PWR_VDD_5V)
    {
        AFIO->CTLR = (AFIO->CTLR & ~(UDP_PUE_MASK | UDM_PUE_MASK | USB_PHY_V33)) | UDP_PUE_10K | USB_IOEN;
    }
    else
    {
        AFIO->CTLR = (AFIO->CTLR & ~(UDP_PUE_MASK | UDM_PUE_MASK )) | USB_PHY_V33 | UDP_PUE_1K5 | USB_IOEN;
    }

    NVIC_InitTypeDef NVIC_InitStructure = { 0 };
    NVIC_InitStructure.NVIC_IRQChannel = USBFS_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}